package com.mlethe.library.immersionbar;

import android.app.Activity;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Color;
import android.os.Build;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowInsets;
import android.view.WindowInsetsController;
import android.view.WindowManager;
import android.widget.LinearLayout;

import androidx.annotation.ColorInt;
import androidx.annotation.ColorRes;
import androidx.annotation.RequiresApi;
import androidx.core.content.ContextCompat;
import androidx.drawerlayout.widget.DrawerLayout;

/**
 * 沉浸式状态栏
 *
 * @author Mlethe
 * @date 2020/8/6
 */
public class ImmersionBar {

    private Window mWindow;
    private ViewGroup mDecorView;
    /**
     * 隐藏Bar
     * The Bar hide.
     */
    private BarHide mBarHide = BarHide.FLAG_SHOW_BAR;
    /**
     * 是否启用 自动根据StatusBar颜色调整深色模式与亮色模式
     * The Auto status bar dark mode enable.
     */
    private boolean autoStatusBarDarkModeEnable = false;
    /**
     * 是否启用 自动根据NavigationBar颜色调整深色模式与亮色模式
     * The Auto navigation bar dark mode enable.
     */
    private boolean autoNavigationBarDarkModeEnable = false;

    /**
     * 状态栏颜色
     * The Status bar color.
     */
    @ColorInt
    private int mStatusBarColor = 0x66000000;
    /**
     * 状态栏字体深色与亮色标志位  true：深色，false：亮色
     * The Dark font.
     */
    public boolean statusBarDarkFont = false;
    /**
     * 是否可以修改状态栏颜色
     * The Status bar flag.
     */
    private boolean statusBarColorEnabled = false;
    /**
     * 导航栏颜色
     * The Navigation bar color.
     */
    @ColorInt
    public int mNavigationBarColor = 0x1A000000;
    /**
     * 导航栏图标深色与亮色标志位
     * The Navigation bar dark icon.
     */
    public boolean navigationBarDarkIcon = false;
    /**
     * 是否能修改导航栏颜色
     * The Navigation bar enable.
     */
    public boolean navigationBarEnable = false;

    private ImmersionBar(Activity activity) {
        this.mWindow = activity.getWindow();
        this.mDecorView = (ViewGroup) mWindow.getDecorView();
    }

    /**
     * 在Activity使用
     * With immersion bar.
     *
     * @param activity the activity
     * @return the immersion bar
     */
    public static ImmersionBar with(Activity activity) {
        return new ImmersionBar(activity);
    }

    /**
     * 隐藏导航栏或状态栏
     *
     * @param barHide the bar hide
     * @return the immersion bar
     */
    public ImmersionBar hideBar(BarHide barHide) {
        this.mBarHide = barHide;
        if (mBarHide == BarHide.FLAG_IMMERSIVE_BAR) {
            this.statusBarColorEnabled = true;
            this.navigationBarEnable = true;
        } else if (mBarHide == BarHide.FLAG_IMMERSIVE_STATUS_BAR) {
            this.statusBarColorEnabled = true;
        } else if (mBarHide == BarHide.FLAG_IMMERSIVE_NAVIGATION_BAR) {
            this.navigationBarEnable = true;
        }
        return this;
    }

    /**
     * 是否启用 自动根据StatusBar和NavigationBar颜色调整深色模式与亮色模式
     *
     * @param isEnable true启用 默认false
     * @return the immersion bar
     */
    public ImmersionBar autoDarkModeEnable(boolean isEnable) {
        this.autoStatusBarDarkModeEnable = isEnable;
        this.autoNavigationBarDarkModeEnable = isEnable;
        return this;
    }

    /**
     * 状态栏颜色
     *
     * @param statusBarColor 状态栏颜色
     * @return the immersion bar
     */
    public ImmersionBar statusBarColorInt(@ColorInt int statusBarColor) {
        this.statusBarColorEnabled = true;
        this.mStatusBarColor = statusBarColor;
        return this;
    }

    /**
     * 状态栏颜色
     *
     * @param statusBarColor 状态栏颜色，资源文件（R.color.xxx）
     * @return the immersion bar
     */
    public ImmersionBar statusBarColor(@ColorRes int statusBarColor) {
        return statusBarColorInt(ContextCompat.getColor(mWindow.getContext(), statusBarColor));
    }

    /**
     * 状态栏颜色
     * Status bar color int immersion bar.
     *
     * @param statusBarColor the status bar color
     * @return the immersion bar
     */
    public ImmersionBar statusBarColor(String statusBarColor) {
        return statusBarColorInt(Color.parseColor(statusBarColor));
    }

    /**
     * 状态栏字体深色或亮色，判断设备支不支持状态栏变色来设置状态栏透明度
     * Status bar dark font immersion bar.
     *
     * @param isDarkFont the is dark font
     * @return the immersion bar
     */
    public ImmersionBar statusBarDarkFont(boolean isDarkFont) {
        this.statusBarDarkFont = isDarkFont;
        return this;
    }

    /**
     * 状态栏支不支持变色
     * Title bar immersion bar.
     *
     * @param statusBarColorTransformEnable the status bar flag 默认为true false表示状态栏不支持变色，true表示状态栏支持变色
     * @return the immersion bar
     */
    public ImmersionBar statusBarColorEnabled(boolean statusBarColorTransformEnable) {
        this.statusBarColorEnabled = statusBarColorTransformEnable;
        return this;
    }

    /**
     * 导航栏颜色
     *
     * @param navigationBarColor the navigation bar color 导航栏颜色
     * @return the immersion bar
     */
    public ImmersionBar navigationBarColorInt(@ColorInt int navigationBarColor) {
        this.navigationBarEnable = true;
        this.mNavigationBarColor = navigationBarColor;
        return this;
    }

    /**
     * 导航栏颜色
     *
     * @param navigationBarColor the navigation bar color 导航栏颜色
     * @return the immersion bar
     */
    public ImmersionBar navigationBarColor(@ColorRes int navigationBarColor) {
        return navigationBarColorInt(ContextCompat.getColor(mWindow.getContext(), navigationBarColor));
    }

    /**
     * 导航栏颜色
     *
     * @param navigationBarColor the navigation bar color 导航栏颜色
     * @return the immersion bar
     */
    public ImmersionBar navigationBarColor(String navigationBarColor) {
        return navigationBarColorInt(Color.parseColor(navigationBarColor));
    }

    /**
     * 导航栏图标深色或亮色，只支持android o以上版本，判断设备支不支持导航栏图标变色来设置导航栏透明度
     * Navigation bar dark icon immersion bar.
     *
     * @param isDarkIcon the is dark icon
     * @return the immersion bar
     */
    public ImmersionBar navigationBarDarkIcon(boolean isDarkIcon) {
        this.navigationBarDarkIcon = isDarkIcon;
        return this;
    }

    /**
     * 是否可以修改导航栏颜色，默认为true
     * 优先级 navigationBarEnable  > navigationBarWithKitkatEnable > navigationBarWithEMUI3Enable
     * Navigation bar enable immersion bar.
     *
     * @param navigationBarEnable the enable
     * @return the immersion bar
     */
    public ImmersionBar navigationBarEnable(boolean navigationBarEnable) {
        this.navigationBarEnable = navigationBarEnable;
        return this;
    }

    /**
     * 通过上面配置后初始化后方可成功调用
     */
    public void init() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
            // android 11.0以上，包含11.0
            // 适配刘海屏
            fitsNotchScreen();
            // 初始化android 11.0以上状态栏和导航栏
            initBarAboveR();
        } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            // 适配刘海屏
            fitsNotchScreen();
            // 防止系统栏隐藏时内容区域大小发生变化
            int uiFlags = View.SYSTEM_UI_FLAG_LAYOUT_STABLE;
            // 初始化5.0以上，包含5.0 隐藏状态栏或者导航栏
            uiFlags = initBarAboveLOLLIPOP(uiFlags);
            // android 6.0以上设置状态栏字体为暗色
            uiFlags = setBarDarkFont(uiFlags);
            uiFlags |= View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
            mDecorView.setSystemUiVisibility(uiFlags);
        } else {
            // 初始化5.0以下，4.4以上沉浸式
            initBarBelowLOLLIPOP();
        }
        mWindow = null;
    }

    /**
     * 适配刘海屏
     * Fits notch screen.
     */
    private void fitsNotchScreen() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
            WindowManager.LayoutParams lp = mWindow.getAttributes();
            lp.layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
            mWindow.setAttributes(lp);
        }
    }

    /**
     * 初始化android 11.0以上状态栏和导航栏
     */
    @RequiresApi(api = Build.VERSION_CODES.R)
    private void initBarAboveR() {
        WindowInsetsController windowInsetsController = mDecorView.getWindowInsetsController();
        if (mBarHide == BarHide.FLAG_HIDE_BAR) {
            if (windowInsetsController != null) {
                windowInsetsController.hide(WindowInsets.Type.statusBars());
                windowInsetsController.hide(WindowInsets.Type.navigationBars());
            }
        } else if (mBarHide == BarHide.FLAG_HIDE_STATUS_BAR) {
            if (windowInsetsController != null) {
                windowInsetsController.hide(WindowInsets.Type.statusBars());
            }
        } else if (mBarHide == BarHide.FLAG_HIDE_NAVIGATION_BAR) {
            if (windowInsetsController != null) {
                windowInsetsController.hide(WindowInsets.Type.navigationBars());
            }
        } else {
            if (mBarHide == BarHide.FLAG_SHOW_BAR || mBarHide == BarHide.FLAG_SHOW_STATUS_BAR || mBarHide == BarHide.FLAG_IMMERSIVE_BAR || mBarHide == BarHide.FLAG_IMMERSIVE_STATUS_BAR) {
                if (windowInsetsController != null) {
                    windowInsetsController.show(WindowInsets.Type.statusBars());
                }
            }
            if (mBarHide == BarHide.FLAG_SHOW_BAR || mBarHide == BarHide.FLAG_SHOW_NAVIGATION_BAR || mBarHide == BarHide.FLAG_IMMERSIVE_BAR || mBarHide == BarHide.FLAG_IMMERSIVE_NAVIGATION_BAR) {
                if (windowInsetsController != null) {
                    windowInsetsController.show(WindowInsets.Type.navigationBars());
                }
            }
            if (mBarHide == BarHide.FLAG_IMMERSIVE_BAR || mBarHide == BarHide.FLAG_IMMERSIVE_STATUS_BAR || mBarHide == BarHide.FLAG_IMMERSIVE_NAVIGATION_BAR) {
                mWindow.setDecorFitsSystemWindows(false);
            } else {
                mWindow.setDecorFitsSystemWindows(true);
            }
            // android 6.0以上设置状态栏背景色
            setBarColor();
            // android 11.0以上设置状态栏字体为暗色
            setBarDarkFont(windowInsetsController);
        }
    }

    /**
     * Sets status bar background color.
     * 设置状态栏和导航栏背景色，android6.0以上
     */
    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    private void setBarColor() {
        // 需要设置这个才能设置状态栏和导航栏颜色
        if (statusBarColorEnabled || navigationBarEnable) {
            mWindow.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
        }
        // 设置状态栏颜色
        if (statusBarColorEnabled) {
            mWindow.setStatusBarColor(mStatusBarColor);
        }
        // 设置导航栏颜色
        if (navigationBarEnable) {
            mWindow.setNavigationBarColor(mNavigationBarColor);
        }
    }

    /**
     * Sets status bar dark font.
     * 设置状态栏字体颜色和导航栏图标颜色，android11.0以上
     */
    private void setBarDarkFont(WindowInsetsController windowInsetsController) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
            if (autoStatusBarDarkModeEnable) {
                statusBarDarkFont = !(mStatusBarColor <= Constants.IMMERSION_BOUNDARY_COLOR || (mStatusBarColor >> 24 & 0xff) > Constants.IMMERSION_BOUNDARY_COLOR_ALPHA);
            }
            if (statusBarDarkFont) {
                windowInsetsController.setSystemBarsAppearance(WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS, WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS);
            } else {
                windowInsetsController.setSystemBarsAppearance(0, WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS);
            }
            if (autoNavigationBarDarkModeEnable) {
                navigationBarDarkIcon = !(mNavigationBarColor <= Constants.IMMERSION_BOUNDARY_COLOR || (mNavigationBarColor >> 24 & 0xff) > Constants.IMMERSION_BOUNDARY_COLOR_ALPHA);
            }
            if (navigationBarDarkIcon) {
                windowInsetsController.setSystemBarsAppearance(WindowInsetsController.APPEARANCE_LIGHT_NAVIGATION_BARS, WindowInsetsController.APPEARANCE_LIGHT_NAVIGATION_BARS);
            } else {
                windowInsetsController.setSystemBarsAppearance(0, WindowInsetsController.APPEARANCE_LIGHT_NAVIGATION_BARS);
            }
        }
    }

    /**
     * 初始化android 5.0以上状态栏和导航栏
     *
     * @param uiFlags the ui flags
     * @return the int
     */
    private int initBarAboveLOLLIPOP(int uiFlags) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && Build.VERSION.SDK_INT < Build.VERSION_CODES.R) {
            if (mBarHide == BarHide.FLAG_HIDE_BAR) {
                uiFlags |= View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
                        | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
                        | View.INVISIBLE;
            } else if (mBarHide == BarHide.FLAG_HIDE_STATUS_BAR) {
                uiFlags |= View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.INVISIBLE;
            } else if (mBarHide == BarHide.FLAG_HIDE_NAVIGATION_BAR) {
                uiFlags |= View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
                        | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
            } else if (mBarHide == BarHide.FLAG_SHOW_BAR) {
                uiFlags |= View.SYSTEM_UI_FLAG_VISIBLE;
            } else {
                if (mBarHide == BarHide.FLAG_IMMERSIVE_BAR || mBarHide == BarHide.FLAG_IMMERSIVE_STATUS_BAR || mBarHide == BarHide.FLAG_IMMERSIVE_NAVIGATION_BAR) {
                    // Activity全屏显示，但状态栏不会被隐藏覆盖，状态栏依然可见，Activity顶端布局部分会被状态栏遮住。
                    uiFlags |= View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
                }
                uiFlags |= View.SYSTEM_UI_FLAG_VISIBLE;
                mWindow.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
                // android 6.0以上设置状态栏背景色
                setBarColor();
            }
        }
        return uiFlags;
    }

    /**
     * Sets status bar dark font.
     * 设置状态栏字体颜色和导航栏图标颜色，android6.0以上
     */
    private int setBarDarkFont(int uiFlags) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            if (autoStatusBarDarkModeEnable) {
                statusBarDarkFont = !(mStatusBarColor <= Constants.IMMERSION_BOUNDARY_COLOR || (mStatusBarColor >> 24 & 0xff) > Constants.IMMERSION_BOUNDARY_COLOR_ALPHA);
            }
            if (statusBarDarkFont) {
                uiFlags |= View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
            }
        }
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            if (autoNavigationBarDarkModeEnable) {
                navigationBarDarkIcon = !(mNavigationBarColor <= Constants.IMMERSION_BOUNDARY_COLOR || (mNavigationBarColor >> 24 & 0xff) > Constants.IMMERSION_BOUNDARY_COLOR_ALPHA);
            }
            if (navigationBarDarkIcon) {
                uiFlags |= View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR;
            }
        }
        return uiFlags;
    }

    /**
     * 初始化android 4.4状态栏和导航栏
     */
    private void initBarBelowLOLLIPOP() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT && Build.VERSION.SDK_INT < Build.VERSION_CODES.R) {
            // 透明状态栏
            mWindow.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
        }
        if (mBarHide == BarHide.FLAG_SHOW_BAR) {
            // 创建一个假的状态栏
            setupStatusBarView();
        }
    }

    /**
     * 设置一个可以自定义颜色的状态栏
     */
    private void setupStatusBarView() {
        Context context = mWindow.getContext();
        View statusBarView = new View(context);
        LinearLayout.LayoutParams statusBarParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, getStatusBarHeight(context));
        statusBarView.setLayoutParams(statusBarParams);
        if (statusBarColorEnabled) {
            statusBarView.setBackgroundColor(mStatusBarColor);
        } else {
            statusBarView.setBackgroundColor(Color.TRANSPARENT);
        }
        // 留出高度 setFitsSystemWindows true代表会调整布局，会把状态栏的亮度留出来
        ViewGroup androidContainer = (ViewGroup) mDecorView.getChildAt(0);
        if (androidContainer != null) {
            androidContainer.setFitsSystemWindows(true);
            androidContainer.setClipToPadding(true);
            androidContainer.addView(statusBarView, 0);
        }
    }

    private Context getContext() {
        if (mWindow != null) {
            return mWindow.getContext();
        }
        return null;
    }

    /**
     * 获取状态栏高度
     * @return
     */
    private int getStatusBarHeight() {
        return getStatusBarHeight(getContext());
    }

    /**
     * 获取状态栏高度
     * @return
     */
    private int getStatusBarHeight(Context context) {
        return getInternalDimensionSize(context, Constants.IMMERSION_STATUS_BAR_HEIGHT);
    }

    /**
     * 获取指定名称的dimen
     *
     * @param context
     * @param key
     * @return
     */
    private int getInternalDimensionSize(Context context, String key) {
        int result = 0;
        try {
            int resourceId = Resources.getSystem().getIdentifier(key, "dimen", "android");
            if (resourceId > 0) {
                int sizeOne = context.getResources().getDimensionPixelSize(resourceId);
                int sizeTwo = Resources.getSystem().getDimensionPixelSize(resourceId);

                if (sizeTwo >= sizeOne) {
                    return sizeTwo;
                } else {
                    float densityOne = context.getResources().getDisplayMetrics().density;
                    float densityTwo = Resources.getSystem().getDisplayMetrics().density;
                    float f = sizeOne * densityTwo / densityOne;
                    return (int) ((f >= 0) ? (f + 0.5f) : (f - 0.5f));
                }
            }
        } catch (Resources.NotFoundException ignored) {
            return 0;
        }
        return result;
    }
}
